# -*- coding: utf-8 -*-
import json
import time
import logging

from api.coupon.model import CouponLite

from common.cache import redis_cache
from common.coupon.model import COUPON_STATUS, CouponTemplate, AccountCoupon
from common.coupon import db  as coupon_db
from common.account.db.account import exists_phone
from common.utils.respcode import StatusCode
from common.utils.tz import now_ts, ts_to_local_date_str
from common.utils.exceptions import ParamError, ResourceInsufficient, AuthenticateError, ResourceNotFound
from common.utils import tracker

_LOGGER = logging.getLogger('bigbang')
_DEFAULT_PAGE_SIZE = 30

coupon_templates = {template.id: template for template in coupon_db.get_all_coupon_templates()}
last_ts = int(time.time())


def _get_coupon_templates():
    global coupon_templates, last_ts
    now = int(time.time())
    if now - last_ts > 60:
        coupon_templates = {template.id: template for template in coupon_db.get_all_coupon_templates()}
        last_ts = now
    return coupon_templates


def check_coupon_valid(coupon_tid, activity_type, bet_type):
    coupon_template = _get_coupon_templates().get(coupon_tid, None)
    if not coupon_template:  # 如果缓存没更新
        return False
    if coupon_template.activity_type in (None, 0, activity_type) and coupon_template.bet_type in (None, 0, bet_type):
        return True
    else:
        return False


def _create_coupon_lite(coupon):
    coupon_lite = CouponLite()
    coupon_lite.id = coupon.id
    coupon_lite.source = coupon.title
    coupon_lite.title = coupon.generate_title()
    coupon_lite.desc = coupon.desc
    coupon_lite.type = coupon.coupon_type
    coupon_lite.price = coupon.price
    coupon_lite.condition_price = coupon.condition_price
    coupon_lite.status = coupon.status

    coupon_tempalte = _get_coupon_templates()[coupon.template_id]
    coupon_lite.cmd = coupon_tempalte.cmd
    coupon_lite.remark = coupon_tempalte.remark
    coupon_lite.bet_type = coupon_tempalte.bet_type
    coupon_lite.start_date = ts_to_local_date_str(coupon.start_ts, f='%Y-%m-%d %H:%M:%S')
    coupon_lite.end_date = ts_to_local_date_str(coupon.expire_ts, f='%Y-%m-%d %H:%M:%S')
    return coupon_lite


def _create_coupon_lite_list(coupons, status=None):
    coupon_list = []
    now = now_ts()
    for coupon in coupons:
        coupon_lite = CouponLite()
        coupon_lite.id = coupon.id
        coupon_lite.temp_id = coupon.template_id
        coupon_lite.title = coupon.generate_title()
        coupon_lite.source = coupon.title
        if u'（' in coupon.desc:
            coupon_lite.desc = coupon.desc[:coupon.desc.index(u'（')]
        elif '(' in coupon.desc:
            coupon_lite.desc = coupon.desc[:coupon.desc.index('(')]
        else:
            coupon_lite.desc = coupon.desc

        if not coupon_lite.desc and coupon.condition_price:
            coupon_lite.desc = u"满{}减{}".format(coupon.condition_price, coupon.price)
        coupon_lite.type = coupon.coupon_type
        coupon_lite.price = coupon.price
        coupon_lite.condition_price = coupon.condition_price
        coupon_lite.status = coupon.status

        coupon_template = _get_coupon_templates()[coupon.template_id]
        coupon_lite.cmd = coupon_template.cmd
        coupon_lite.remark = coupon_template.remark
        coupon_lite.bet_type = coupon_template.bet_type
        coupon_lite.activity_type = coupon_template.activity_type
        if coupon.status == COUPON_STATUS.UNUSED and now > coupon.expire_ts:
            coupon_lite.status = COUPON_STATUS.EXPIRED
        if coupon.status == COUPON_STATUS.UNUSED and now < coupon.start_ts:
            coupon_lite.will_be_used = 1
        if status and not (status & coupon_lite.status):
            continue

        coupon_lite.start_date = ts_to_local_date_str(coupon.start_ts, f='%Y-%m-%d %H:%M:%S')
        coupon_lite.end_date = ts_to_local_date_str(coupon.expire_ts, f='%Y-%m-%d %H:%M:%S')
        coupon_lite.expire_ts = coupon.expire_ts
        coupon_list.append(coupon_lite)
    return sorted(coupon_list, key=lambda x: x['expire_ts'])


def check_coupon_scope(coupon_tid, buy_list):
    for each in buy_list:
        if not check_coupon_valid(coupon_tid, each['activity_type']):
            return False
    return True


def view_user_coupons(user_id, status, page, size):
    limit = _DEFAULT_PAGE_SIZE if not size or size > _DEFAULT_PAGE_SIZE else size
    if not page or page < 1:
        page = 1
    offset = 0 if not page else (page - 1) * limit
    coupons, count = coupon_db.get_user_coupons(user_id, status, limit, offset)
    return _create_coupon_lite_list(coupons, status), count


def view_user_fresh_coupons(user_id):
    coupons = coupon_db.get_user_fresh_coupons(user_id)
    raw_list = _create_coupon_lite_list(coupons)
    return sorted(raw_list, key=lambda x: x['temp_id'])


def view_available_coupons(user_id, price, activity_type, bet_type):
    now = now_ts()
    coupons = coupon_db.get_unused_coupons(user_id)
    coupons = filter(lambda coupon: check_coupon_valid(coupon.template_id, activity_type, bet_type), coupons)
    coupons = filter(lambda coupon: coupon.start_ts < now < coupon.expire_ts, coupons)
    coupons = filter(lambda coupon: not (coupon.condition_price and price < coupon.condition_price), coupons)
    coupons = filter(lambda coupon: coupon.price <= price, coupons)
    if not coupons:
        raise ResourceNotFound('no available coupon')

    available_coupons = _create_coupon_lite_list(coupons, status=COUPON_STATUS.UNUSED)
    available_coupons.sort(key=lambda x: x.end_date, reverse=True)
    return available_coupons


def send_coupon_to_user(user_id, template_id, count, extend=None, start_ts=None, coupon_from=None):
    try:
        template = coupon_db.get_coupon_template(template_id)
        source_type = get_source_type(template_id)
        for _ in range(count):
            coupon = AccountCoupon.create_from_template(
                template, user_id, extend=extend, start_ts=start_ts, source_type=source_type)
            coupon.save()
            AccountCoupon.start_expire_timer(coupon.id, coupon.expire_ts)
            log_data = coupon.as_dict()
            log_data.update({
                'from': coupon_from
            })
            tracker.track_coupon(log_data, action='create')
        _LOGGER.info("add user coupon: %s, user: %s, count: %s", template_id, user_id, count)
    except Exception as e:
        _LOGGER.exception('add user coupon exception, %s-%s, %s', user_id, template_id, e)


def get_recommend_coupon(user_id, price, activity_type, bet_type):
    now = now_ts()
    coupons = coupon_db.get_unused_coupons(user_id)
    coupons = filter(lambda coupon: check_coupon_valid(coupon.template_id, activity_type, bet_type), coupons)
    coupons = filter(lambda coupon: coupon.start_ts < now < coupon.expire_ts, coupons)
    coupons = filter(lambda coupon: not (coupon.condition_price and price < coupon.condition_price), coupons)
    coupons = filter(lambda coupon: coupon.price <= price, coupons)
    if not coupons:
        raise ResourceNotFound('no available coupon')
    if len(coupons) == 1:
        coupon = coupons[0]
    else:
        max_price = max([coupon.price for coupon in coupons])
        coupons = filter(lambda coupon: coupon.price == max_price, coupons)
        if len(coupons) == 1:
            coupon = coupons[0]
        else:
            min_expire_ts = min([coupon.expire_ts for coupon in coupons])
            coupons = filter(lambda coupon: coupon.expire_ts == min_expire_ts, coupons)
            coupon = coupons[0]
    return _create_coupon_lite(coupon)


def get_fresh_coupons_temp():
    temps = coupon_db.get_fresh_coupon_templates()
    temp_list = []
    for temp in temps:
        temp_dict = {
            'id': temp.id,
            'cmd': temp.cmd,
            'remark': temp.remark,
            'bet_type': temp.bet_type,
            'activity_type': temp.activity_type,
            'price': temp.price
        }
        temp_list.append(temp_dict)
    return sorted(temp_list, key=lambda x: x['id'])


def get_source_type(template_id):
    source_type = CouponTemplate.query.filter(CouponTemplate.id == template_id).first().source_type
    return source_type
